home *** CD-ROM | disk | FTP | other *** search
/ Merciful 1 / Merciful - Disc 1.iso / software / f / friday_night_pool / fridaynightpool.dms / fridaynightpool.adf / source / fnpool.c < prev    next >
C/C++ Source or Header  |  1978-02-25  |  29KB  |  1,061 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <graphics/view.h>
  4. #include <intuition/intuition.h>
  5. #include <graphics/gfxmacros.h>
  6. #include <proto/exec.h>
  7. #include <proto/graphics.h>
  8. #include <proto/intuition.h>
  9. #include <dos.h>
  10. #include <proto/dos.h>
  11. #include <math.h>
  12. #include <exec/devices.h>
  13. #include <devices/audio.h>
  14. #include <hardware/custom.h>
  15.  
  16. #define CUE 0
  17. #define BLK 5
  18. #define GREENBAIZE 0
  19. #define BLUEBAIZE 1
  20.  
  21. #define BASE 200 /* V.important constant. Used in ALL physical calcs. */
  22. #define BASESP 1000
  23. #define BASEII 4 /* For root calcs which need plenty of precision */
  24.  
  25. #define TABLELENGTH (272 * BASE) /* 272 is actual length in pixels */
  26. #define TABLEWIDTH ((TABLELENGTH * 5 / 8)-BASE)
  27.  
  28. #define X1CORNER 24
  29. #define Y1CORNER 62
  30. #define X2CORNER (X1CORNER + TABLELENGTH / BASE)
  31. #define Y2CORNER (Y1CORNER + TABLEWIDTH / BASE)
  32.  
  33. #define BALLRADIUS (7 * BASE) /* 7 pixels */
  34. #define BALLDIAMETER (BALLRADIUS * 2)
  35. #define SCRNBALLDIAMETER (BALLDIAMETER / BASE)
  36. #define SEMICIRCRAD (TABLEWIDTH/6)
  37. #define PLACEPACK (TABLELENGTH * 5 / 8)
  38. #define PACKHORIZSEP (BALLDIAMETER - 2*BASE)
  39. #define POCKET (BALLRADIUS + 5*BASE)
  40. #define SCRNPOCKET (POCKET / BASE)
  41. #define CUETIP 10
  42. #define MAXCUELENGTH 80
  43.  
  44. #define CLOCKWISE 1
  45. #define ANTICLOCKWISE 2
  46. #define SMALL 1
  47. #define LARGE 2
  48. #define UP 1
  49. #define DOWN 2
  50. #define NOHIT -1
  51. #define ON TRUE
  52. #define OFF FALSE
  53. #define HIT 3
  54. #define UPDATE 3
  55. #define ICON 2
  56. #define VIEW 1
  57. #define NOREFRESH 2
  58.  
  59. #define RACKED 1
  60. #define BROKEN 0
  61. #define OPEN 2
  62. #define SPREAD 3
  63.  
  64. #undef SINGLE
  65.  
  66. enum icons { PLYR1,PLYR2,PRACTICE,DEMO,PLAY,QUIT,_BAIZE,_BALL1,_BALL2,
  67.     SINGLE,BEST3,BEST5,UNLIMITED,STRIP,BALL10,BALL16,
  68.     OPPONENTBASE,ICON17,ICON18,ICON19,STRIPPERBASE };
  69.  
  70. enum args { GAMETYPE,GAMELENGTH,BAIZE,BALL1,BALL2,BALLCOUNT,OPPONENT,STRIPPER };
  71.  
  72. #define HUMANPLYR 0
  73. #define COMPLYR   1
  74.  
  75. #define FRICTION (BASESP / 300)
  76. #define SPINFRICTION 3
  77. #define SPEEDINC (BASESP / 16)
  78. #define MAXSPEED (BASESP * 4)
  79. #define MINSPEED (BASESP / 4)
  80.  
  81. #define ESC 69
  82. #define RETURN 68
  83. #define SPACE 64
  84. #define HELP 95
  85. #define LCSR 79
  86. #define RCSR 78
  87. #define UCSR 76
  88. #define DCSR 77
  89. #define F1 80
  90. #define F2 81
  91. #define F3 82
  92. #define F4 83
  93. #define F5 84
  94. #define F6 85
  95. #define F7 86
  96. #define F8 87
  97. #define F9 88
  98. #define F10 89
  99.  
  100. #define FLASH 2
  101.  
  102. #define JOYFIRE 0xbfe001
  103. #define LMOUSE 1
  104. #define RMOUSE 2
  105.  
  106. #define MEMSIZE 7000
  107.  
  108. void DoControl(void);
  109. void DrawCue(short);
  110. void ChangePower();
  111. short ChangeSpin(void);
  112. void DrawCross(short);
  113. void MoveCue(short,short);
  114. void DoAssigns(void);
  115. void SetUpTable(void);
  116. void DoOptions(void);
  117. short GetInput(void);
  118. char UpdateBallPos(void);
  119. void WaitBeam(short);
  120. short CheckPotted(short);
  121. void CheckBounce(short);
  122. void CheckCollision(void);
  123. void MakeCollision(short,short);
  124. void DrawBall(short,short);
  125. void DrawBallDirect(short,short,short);
  126. short FindAngle(WORD,WORD,WORD);
  127. void SuperImpose(struct RastPort *,short,short,struct RastPort *,
  128.     short,short,short,short,short,short);
  129. void WriteMessage(short,short,short,short);
  130. void ScrubMessage(void);
  131. void PlayShot(void);
  132. void CheckResult(void);
  133. void CheckWhitePotted(void);
  134. short TouchingBall(short);
  135. void PlayComputerShot(void);
  136. void CheckBallDrag(void);
  137. void CopyBalls(struct ballstruct*,struct ballstruct*);
  138. void CopyPlayer(short,short);
  139. WORD QuickRoot(long);
  140. short GetMouse(void);
  141. char LoadIFF(struct IFFGraphic *,struct Screen *,char);
  142. char ClickDelay(short);
  143. void CueJumpAnim(void);
  144. void CheckAngle(short *);
  145. UWORD Rand(UWORD);
  146. long MyRead(struct FileHandle *,long *,long);
  147. char OpenIt(void);
  148. void CloseIt(void);
  149.  
  150. APTR GetDeviceBlock(ULONG);
  151. void FreeDeviceBlock(struct IOAudio *,BYTE);
  152. void Audio_PerVol(struct IOAudio *,UWORD,UWORD);
  153. void Audio_Write(struct IOAudio *,UBYTE *,UWORD);
  154. void PlaySound(struct audioinfostruct *,short);
  155.  
  156. /******************* Graphics defines ******************/
  157. struct NewScreen ns =
  158. {
  159.     0,0,            /* Left edge, top */
  160.     320,256,        /* Width, height */
  161.     5,            /* Depth (32 colours) */
  162.     0,1,            /* Detail, block pens */
  163.     0,            /* Modes for ViewPort */
  164.     CUSTOMSCREEN | SCREENQUIET,
  165.                 /* Screen type */
  166.     NULL,        /* Text attributes */
  167.     NULL,        /* Title */
  168.     NULL,        /* Gadget list */
  169.     NULL            /* Custom bitmap pointer */
  170. };
  171.  
  172. struct NewWindow nw =
  173. {
  174.     0,0,            /* Starting corner */
  175.     320,256,        /* Width, height */
  176.     0,1,            /* detail, block pens */
  177.     RAWKEY,        /* IDCMP flags */
  178.     BORDERLESS | ACTIVATE | RMBTRAP,
  179.                 /* Window flags */
  180.     NULL,        /* Pointer to first gadget */
  181.     NULL,        /* Pointer to checkmark */
  182.     NULL,        /* title */
  183.     NULL,        /* screen pointer (don't know yet) */
  184.     NULL,        /* bitmap pointer */
  185.     0,0,0,0,        /* window not sized */
  186.     CUSTOMSCREEN    /* type of screen */
  187. };
  188.  
  189. /* Extra padding for use with tempmask. Must set ballmask to point to */
  190. /* first 'real' byte (8) at start of program */
  191.  
  192. USHORT chip crossmask[5] = { 0x2000,0x2000,0xd800,0x2000,0x2000 };
  193.  
  194. USHORT chip mask[37] = { 0,0,0,0,0,0,0,0,0,0,0,0,
  195.     0x3e0,0xff8,0x1ffc,0x1ffc,0x3ffe,0x3ffe,
  196.     0x3ffe,0x3ffe,0x3ffe,0x1ffc,0x1ffc,0xff8,0x3e0,
  197.     0,0,0,0,0,0,0,0,0,0,0,0 };
  198.  
  199. USHORT chip mask2[10] = { 0x3e0,0xff0,0xff8,0x1ff8,0x1ff8,0x1ff8,
  200.     0x1ff0,0x1ff0,0xfe0,0x780 };
  201.  
  202. USHORT chip hybridmask[13] =
  203.     { 0x3e0,0xff8,0x7fc,0x3fc,0x1fe,0xfe,0x7e,0x3e,0x1e,0xc,0x4,0,0 };
  204.     
  205. USHORT chip hybridmask2[10] =
  206.     { 0x3e0,0x7f0,0x3f8,0x1f8,0x0f8,0x078,0x030,0x010,0,0 };
  207.  
  208. USHORT chip miniball[8] =
  209.     { 0x3c00,0x7e00,0xff00,0xff00,0xff00,0xff00,0x7e00,0x3c00 };
  210.  
  211. USHORT *ballmask = &mask[12];
  212. USHORT *ballmask2 = mask2;
  213. USHORT chip tempmask[256];
  214.  
  215. USHORT chip buffer[20];
  216.  
  217. /********************* System defines ************************/
  218. struct Screen         *s,*s2;
  219. struct Window         *w,*w2;
  220. struct RastPort    *rp,*rp2,bufrp;
  221. struct BitMap        *bm,*bm2,bufbm;
  222. struct ViewPort     *vp;
  223. struct ColorMap     *cm;
  224. struct IntuiMessage *msg;
  225. struct FileHandle    *fh;
  226. struct Preferences  prefs;
  227.  
  228. UWORD *colorpalette;
  229.  
  230. char *bp0,*bp1,*bp2,*bp3,*bp4;
  231.  
  232. extern UWORD chip pointeron[24];
  233. extern UWORD chip pointeroff[8];
  234.  
  235. long oldkeydelay,oldkeyspeed;
  236.  
  237. /******************* Audio Defines ******************/
  238.  
  239. #define SAMPLES 8
  240. #define AM2 106 /* Audio Master II info size */
  241. #define BUFWAVELEN 100
  242.  
  243. enum sound { COLLIDE,STRIKE,BOUNCE,POTTED,CHEER,LONGCHEER,CHANT,CRASH };
  244.  
  245. #define AUDIO_LEN (sizeof(struct IOAudio))
  246. #define PRECIDENCE 127
  247. #define CLOSE_DEVICE 1
  248.  
  249. #define BUFFER 0
  250. #define RESET  1
  251.  
  252. struct IOAudio *audio[4];
  253. char Channel_Map[] = { 1,2,4,8 },*bufwave;
  254.  
  255. struct audioinfostruct
  256. {
  257.     struct IOAudio *audio;
  258.     char *wave,bufstate,channel,flag;
  259.     long wavelen;
  260.     short volume,period;
  261.     char filename[30];
  262. };
  263.  
  264. struct audioinfostruct audioinfo[SAMPLES] = {
  265. { 0,0,0,0,BUFFER,702-AM2,0,320,"FNPAUDIO:collide.sam" },
  266. { 0,0,0,1,BUFFER,544-AM2,0,600,"FNPAUDIO:strike.sam" },
  267. { 0,0,0,2,RESET,448-AM2,0,640,"FNPAUDIO:bounce.sam" },
  268. { 0,0,0,3,BUFFER,1386-AM2,0,315,"FNPAUDIO:pot.sam" },
  269. { 0,0,0,2,RESET,19708-AM2,0,550,"FNPAUDIO:cheer.sam" },
  270. { 0,0,0,2,RESET,36682-AM2,0,550,"FNPAUDIO:cheer2.sam" },
  271. { 0,0,0,2,RESET,20432-AM2,0,536,"FNPAUDIO:chant.sam" },
  272. { 0,0,0,2,RESET,18960-AM2,0,286,"FNPAUDIO:crash.sam" }};
  273.  
  274. /********************* Gameplay defines **********************/
  275.  
  276. UWORD rgb[32];
  277. UWORD rgb2[32] = {
  278.     0x000,0xfb9,0xd86,0x593,0x030,0x400,0x610,0x820,
  279.     0x150,0xfc0,0xf00,0x382,0xfff,0xfff,0xfcc,0x270,
  280.     0x444,0xb8b,0x000,0xfff,0xf83,0xfc7,0x000,0x000,
  281.     0x000,0xfff,0x888,0x000,0x9cf,0x000,0x000,0x000 };
  282.  
  283. enum col {
  284.  _back,_leather,_dkleather,_ltbaize,_dkbaize,_dkwalnut,_walnut,_ltwalnut,
  285.  _baize,_yellow,_red,_ltbaize2,_white,_highyel,_highred,_ltbaize3,
  286.  _cross,_ptr17,_ptr18,_ptr19,_cuecol,_ltcuecol,_22,_23,
  287.  _black,_text1,_text2 };
  288.  
  289. enum balltype { white,black,yellow,red,anyball,baize };
  290. char ballpalette[] = { _white,_black,_yellow,_red, 0,_baize };
  291.  
  292. char ball15colour[16] = {
  293. white,yellow,red,yellow,yellow,black,red,red,
  294. yellow,red,yellow,yellow,red,yellow,red,red };
  295.  
  296. char ball9colour[10] = {
  297. white,red,red,red,red,black,red,red,red,red };
  298.  
  299. char ballplanes[] = { 4,16,1,2, 0,23 };
  300.  
  301. struct ballstruct
  302. {
  303.     enum balltype colour;
  304.     char potted,justpotted,hasmoved,lasthit,olddx,olddy;
  305.     USHORT x,y;
  306.     short speed,angle,scrnx,scrny,oldscrnx,oldscrny;
  307. };
  308. struct ballstruct ball[16],tempball[16];
  309.  
  310. struct pixelsavestruct
  311. {
  312.     char col;
  313.     short x,y;
  314. };
  315. struct pixelsavestruct pixelsave[32];
  316.  
  317. struct blitdatstruct
  318. {
  319.     short x,y,dx,dy;
  320. };
  321. struct blitdatstruct blitdat,blitdat2;
  322.  
  323. char *quickarcsin;
  324. short *memblock,*quicksin,*quickcos,
  325.     cueangle=270,cuespeed=MINSPEED,powerdirn=UP,
  326.     spinx,spiny,swerve,swervetotal,
  327.     gametype,gamelength,stripper,opponent,
  328.     defaultdemo,enableoptions=TRUE,flipoffer,
  329.     cloth,cueline=ON,firsthit,dotspacing=8,cheer=ON,
  330.     plyrbreak,turn,comp1,comp2,
  331.     balls=16,dragcheat,cheatangle=-1,cheatball,
  332.     foul,endofgame,quitgame,winner,matches,coin,packstate,newbreak;
  333.  
  334. USHORT seed; /* random element */
  335.  
  336. USHORT pocketx[6] = { (TABLELENGTH-BALLRADIUS),(TABLELENGTH-BALLRADIUS),
  337.     (TABLELENGTH/2),(TABLELENGTH/2),BALLRADIUS,BALLRADIUS };
  338.  
  339. USHORT pockety[6] = { (TABLEWIDTH-BALLRADIUS),BALLRADIUS,
  340.     (TABLEWIDTH-BALLRADIUS),BALLRADIUS,(TABLEWIDTH-BALLRADIUS),BALLRADIUS };
  341.     
  342. char angleused[360];    
  343.  
  344. char joydelay;
  345.  
  346. extern struct Custom far custom;
  347.  
  348. /********* Loader stuff *************/
  349.  
  350. extern struct IFFGraphic
  351. {
  352. char        FileName[30];    /* Name of IFF file */
  353. BYTE        ReqDepth;        /* How many bitplanes wish to be Displayed */  
  354. USHORT    *RGB;        /* RGB colour values, filled by LoadIFF */ 
  355. short    Width;        /* Width of graphic, filled by LoadIFF */ 
  356. short    Height;        /* Height of graphic, filled by LoadIFF */ 
  357. BYTE        Depth;        /* Depth of graphic, filled by LoadIFF */ 
  358. };
  359.  
  360. extern char arg[8],bufarg[8],demoarg[8];
  361.  
  362. struct IFFGraphic
  363. tableIFF =  { "FNPGRAPHICS:table.img",5,NULL },
  364. offerIFF = { "FNPGRAPHICS:offer.img",5,rgb },
  365. offer2IFF = { "FNPGRAPHICS:offer2.img",5,rgb };
  366.  
  367. UWORD RGBbaize[] = {
  368. 0x593,0x030,0x150,0x382,0x270, /* green */
  369. 0x368,0x023,0x034,0x156,0x145, /* blue */
  370. 0x965,0x421,0x632,0x854,0x743, /* brown */
  371. 0x777,0x333,0x444,0x666,0x555 }; /* grey */
  372.  
  373. UWORD RGBball[] = { 0xf00,0xf40,0xfa0,0x390,0x05f,0x608,0xf55 };
  374.  
  375. UWORD RGBroom[16];
  376.  
  377. /********** Strip stuff *****************/
  378.  
  379. struct IFFGraphic roomIFF = { "FNPGRAPHICS:room.img",5,RGBroom };
  380.  
  381. struct IFFGraphic stripimageIFF[4] = {
  382. { "FNPGRAPHICS:claire_sally.img",5,rgb },
  383. { "FNPGRAPHICS:michael.img",5,rgb },
  384. { "FNPGRAPHICS:claire_sally.img",5,rgb },
  385. { "FNPGRAPHICS:josh.img",5,rgb }};
  386.  
  387. struct IFFGraphic striptextIFF[4] = {
  388. { "FNPGRAPHICS:quotes.img",5,rgb },
  389. { "FNPGRAPHICS:quotes.img",5,rgb },
  390. { "FNPGRAPHICS:quotes.img",5,rgb },
  391. { "FNPGRAPHICS:quotes2.img",5,rgb }};
  392.  
  393. struct stripstruct
  394. {
  395.     short imgx1[4],imgy1[4],imgdx[4],imgdy[4],imgx2[4],imgy2[4],
  396.          textx[5],texty[5],textdx[5],textdy[5];
  397. };
  398.  
  399. struct stripstruct stripinfo[4] = {
  400. { 192,129,65,0, 0,0,0,0, 60,60,60,60,
  401.   139,139,139,139, 19,19,19,19, 68,68,68,68,
  402.   0,113,89,0,207, 0,0,39,39,39, 112,200,117,88,88, 32,39,39,32,32 },
  403.  
  404. { 195,128,61,0, 0,0,0,0, 65,65,65,58,
  405.   149,149,149,149, 11,11,11,11, 57,57,57,57,
  406.   135,0,0,237,148, 80,172,211,153,153, 110,147,118,82,88, 32,39,41,53,32 },
  407.  
  408. { 211,140,70,0, 139,139,139,139, 67,67,67,67,
  409.   112,112,112,112, 27,27,27,27, 90,90,90,90,
  410.   0,135,0,224,245, 133,113,80,113,80, 117,88,133,81,75, 39,32,53,39,32 },
  411.  
  412. { 170,108,57,0, 0,0,0,0, 56,56,50,50,
  413.   171,171,161,161, 17,28,23,23, 50,51,50,50,
  414.   0,0,171,0,139, 60,0,0,106,60, 139,171,149,131,113, 46,60,53,46,53 }};
  415.  
  416. /******* Message stuff *****************/
  417.  
  418. #define NEW 0
  419. #define FOLLOW 1
  420.  
  421. enum msg { MSG_PLACECUEBALL,MSG_FOUL,MSG_WINS,MSG_MICHAEL,MSG_JOSH,
  422.     MSG_CLAIRE,MSG_SALLY,MSG_PLAYER1,MSG_PLAYER2,MSG_QUITTING,
  423.     MSG_VS,MSG_GAME,MSG_OF,MSG_0,MSG_1,MSG_2,MSG_3,MSG_4,MSG_5,
  424.     MSG_GOODSHOT,MSG_SHOTCANCELLED,MSG_BADLUCK,MSG_WELLDONE,
  425.     MSG_QUITGAME,MSG_ISTHECHAMP,MSG_OOOPS };
  426.  
  427. short cursor;
  428.  
  429. struct messagestruct { short x1,y1,x2,y2; };
  430. struct messagestruct message[] = {
  431. { 0,0,122,13 }, { 123,0,174,13 }, { 175,0,214,13 }, { 215,0,275,13 },
  432. { 276,0,313,13 },
  433.  
  434. { 0,14,44,31 }, { 45,14,82,31 }, { 83,14,144,31 },
  435. { 145,14,208,31 }, { 209,14,284,31 }, { 285,14,301,31 },
  436.  
  437. { 0,32,44,45 }, { 45,32,60,45 }, { 240,60,253,77 }, { 61,32,64,45 },
  438. { 65,32,72,45 }, { 73,32,80,45 }, { 81,32,89,45 }, { 90,32,97,45 },
  439. { 98,32,196,45 }, { 197,32,317,45 },
  440.  
  441. { 0,46,74,59 }, { 75,46,160,59 },
  442.     
  443. { 0,60,127,77 }, { 128,60,239,77 }, { 240,60,299,77 }};
  444.  
  445. /************ Player stuff **************/
  446.  
  447. struct playerstruct
  448. {
  449.     enum balltype colour;
  450.     char goes,wins;
  451.     char nametag;
  452.     short maxpower;
  453.     char cuepulls,skill;
  454. };
  455.  
  456. struct playerstruct player[8] = {
  457. { 0,0,0,0,MAXSPEED,0,0 }, /* Filled 1 */
  458. { 0,0,0,0,MAXSPEED,0,0 }, /* Filled 2 */
  459.  
  460. { 0,0,0,MSG_PLAYER1,MAXSPEED,1,3 }, /* Player 1 */
  461. { 0,0,0,MSG_PLAYER2,MAXSPEED,1,3 }, /* Player 2 */
  462. { 0,0,0,MSG_CLAIRE,MAXSPEED,2,0 }, /* Claire */
  463. { 0,0,0,MSG_MICHAEL,MAXSPEED+MAXSPEED/2,0,2 }, /* Mike */
  464. { 0,0,0,MSG_SALLY,MAXSPEED-MAXSPEED/4,1,3 }, /* Sally */
  465. { 0,0,0,MSG_JOSH,MAXSPEED,3,3 }}; /* Josh */
  466.  
  467. /**********************/
  468. main()
  469. {
  470.     short i,match;
  471.     
  472.     if (!OpenIt()) { CloseIt(); return; }
  473.     DoAssigns();
  474.     if (Loader(1)) do
  475.     {
  476.         coin=-1; DoOptions();
  477.         switch(gamelength)
  478.         {
  479.             case BEST3:
  480.             case BEST5:
  481.                 for(match=0; match<matches; match++)
  482.                 {
  483.                     WriteMessage(MSG_GAME,5,5,NEW);
  484.                     WriteMessage(MSG_1+match,0,5,FOLLOW);
  485.                     WriteMessage(MSG_OF,0,5,FOLLOW);
  486.                     WriteMessage((MSG_1-1)+matches,0,5,FOLLOW);
  487.                     SetUpTable(); Delay(100); DoControl();
  488.                     if (player[0].wins>matches/2 ||
  489.                         player[1].wins>matches/2 ||
  490.                         quitgame) break;
  491.                     WriteMessage(player[1-winner].nametag,5,5,NEW);
  492.                     WriteMessage(MSG_0+player[1-winner].wins,15,5,FOLLOW);
  493.                     Delay(65);
  494.                     WriteMessage(player[winner].nametag,5,5,NEW);
  495.                     WriteMessage(MSG_0+player[winner].wins,15,5,FOLLOW);
  496.                     Delay(65);            
  497.                 }
  498.                 if (!quitgame)
  499.                 {
  500.                     FadeScreen(s,DOWN); SetRast(rp,_back);
  501.                     WriteMessage(player[winner].nametag,60,80,NEW);
  502.                     WriteMessage(MSG_ISTHECHAMP,0,80,FOLLOW);
  503.                     FadeScreen(s,UP); ClickDelay(400);
  504.                 } break;
  505.             case SINGLE:
  506.                 SetUpTable(); DoControl(); break;
  507.             case UNLIMITED:
  508.                 do
  509.                 { SetUpTable(); DoControl(); } while (!quitgame);
  510.                 break;
  511.             case STRIP:
  512.             {
  513.                 short image=0,text=1;
  514.                 
  515.                 for(match=0; match<4;
  516.                     match++,image++,text++)
  517.                 {
  518.                     WriteMessage(MSG_GAME,5,5,NEW);
  519.                     WriteMessage(MSG_1+match,0,5,FOLLOW);
  520.                     WriteMessage(MSG_OF,0,5,FOLLOW);
  521.                     WriteMessage(MSG_4,0,5,FOLLOW);
  522.                     SetUpTable(); Delay(100); DoControl();
  523.                     if (quitgame) break;
  524.                     if (winner==COMPLYR) { text=0; image=0; }
  525.                     
  526.                     FadeScreen(s,DOWN);
  527.                 
  528.                     LoadIFF(&striptextIFF[stripper],s,NOREFRESH);
  529.                     
  530.                     BltBitMap(bm,stripinfo[stripper].textx[text],
  531.                         stripinfo[stripper].texty[text],&bufbm,0,85,
  532.                         stripinfo[stripper].textdx[text],
  533.                         stripinfo[stripper].textdy[text],0xc0,31,buffer);
  534.                     
  535.                     LoadIFF(&stripimageIFF[stripper],s,NOREFRESH);
  536.                     
  537.                     BltBitMap(bm,stripinfo[stripper].imgx1[image],
  538.                         stripinfo[stripper].imgy1[image],&bufbm,250,0,
  539.                         stripinfo[stripper].imgdx[image],
  540.                         stripinfo[stripper].imgdy[image],0xc0,31,buffer);
  541.                     
  542.                     for (i=0; i<16; i++)
  543.                     { rgb[16+i] = rgb[i]; rgb[i] = RGBroom[i]; }
  544.                     
  545.                     BltBitMap(bm2,0,0,bm,0,0,320,256,0xc0,31,buffer);
  546.             
  547.                     SuperImpose(&bufrp,0,85,rp,101,28,
  548.                         stripinfo[stripper].textdx[text],
  549.                         stripinfo[stripper].textdy[text],0,7);
  550.                     
  551.                     SuperImpose(&bufrp,250,0,rp,
  552.                         stripinfo[stripper].imgx2[image],
  553.                         stripinfo[stripper].imgy2[image],
  554.                         stripinfo[stripper].imgdx[image],
  555.                         stripinfo[stripper].imgdy[image],0,16);
  556.                     
  557.                     FadeScreen(s,UP);
  558.                     
  559.                     if (match==3) PlaySound(&audioinfo[LONGCHEER],64);
  560.                     ClickDelay(600);
  561.                     if (match==3 || winner==COMPLYR) break;
  562.                     arg[OPPONENT]++; DoOptions();
  563.                 }
  564.                 break;
  565.             }
  566.         }
  567. /*        enableoptions = FALSE;
  568.         if (flipoffer = 1-flipoffer)
  569.         {
  570.             short flash=0xf00,dirn=-0x100,count=0;
  571.  
  572.             LoadIFF(&offer2IFF,s,VIEW);            
  573.             while (!(GetMouse()) && ++count < 1500)
  574.             {
  575.                 flash+=dirn;
  576.                 if (flash==0xf00 || flash==0x400) dirn = -dirn;
  577.                 colorpalette[1] = flash;
  578.                 MakeScreen(s); RethinkDisplay();
  579.                 Delay(2);
  580.             } 
  581.         }
  582.         else { LoadIFF(&offerIFF,s,VIEW); ClickDelay(1500); }
  583. */        
  584.     } while (Loader(0));
  585.     CloseIt();
  586. }
  587. /**********************/
  588. void CueJumpAnim()
  589. {
  590.     short y=125,x=180,oldx,oldy,crash=FALSE,
  591.         forcex=quicksin[ball[CUE].angle] * 7 / BASE,
  592.         forcey=-12,bounce=0,onscreen=TRUE;
  593.  
  594.     ball[CUE].potted = TRUE; ball[CUE].justpotted = TRUE;
  595.     ball[CUE].scrnx = ball[CUE].oldscrnx;
  596.     ball[CUE].scrny = ball[CUE].oldscrny;
  597.     DrawBall(CUE,OFF);
  598.  
  599.     if (forcex > 4) { forcey = -16; crash = TRUE; }
  600.     
  601.     ScreenToFront(s2); ActivateWindow(w2);
  602.     SetAPen(rp2,8); PlaySound(&audioinfo[POTTED],64);
  603.  
  604.     while(1)
  605.     {
  606.         if (onscreen)
  607.         {
  608.             BltBitMap(bm2,x,y,&bufbm,0,100,8,8,0xc0,31,buffer);        
  609.             BltPattern(rp2,miniball,x,y,x+7,y+7,2);
  610.         }
  611.         else Delay(1);
  612.         oldx = x; oldy = y;
  613.         y+=forcey++/2; x+=forcex;
  614.         if (y >= 220+bounce*4)
  615.         {
  616.             y=220+bounce*2; forcey=-forcey/4; bounce++;
  617.             PlaySound(&audioinfo[BOUNCE],32 + 32/bounce);
  618.         }
  619.         if (bounce==3) Delay(75);
  620.         if (onscreen)
  621.         {
  622.             WaitBeam(oldy+10);
  623.             BltBitMap(&bufbm,0,100,bm2,oldx,oldy,8,8,0xc0,31,buffer);
  624.         }
  625.         if (bounce==3) break;
  626.         if (x < 0 || x > 310)
  627.         {
  628.             if (crash) break;
  629.             onscreen=FALSE;
  630.         }
  631.     }
  632.     if (crash)
  633.     {
  634.         PlaySound(&audioinfo[CRASH],64); Delay(100);
  635.         PlaySound(&audioinfo[CHEER],64);
  636.     }    
  637.     WriteMessage(MSG_OOOPS,30,5,NEW);
  638.     ScreenToFront(s); ActivateWindow(w);
  639. }
  640. /*************************/
  641. void DoControl()
  642. {
  643.     short input,i,key=0;
  644.     
  645.     if (gametype==PRACTICE || dragcheat) SetPointer(w,pointeron,11,11,0,0);
  646.     WriteMessage(player[turn].nametag,5,5,NEW); GetInput();
  647.     quitgame = FALSE; endofgame = FALSE;
  648.     
  649.     do
  650.     {
  651.         input = GetInput();
  652.         
  653.         if (gametype==DEMO || (gametype==PLYR1 && turn==COMPLYR))
  654.         {
  655.             if (input==ESC) quitgame=TRUE;
  656.             else PlayComputerShot();
  657.         }
  658.         else switch(input)
  659.         {
  660.             case ESC: quitgame=TRUE; break;
  661.             
  662.             case RETURN:
  663.                 {
  664.                     BOOL play=TRUE;
  665.                 
  666.                     if (ChangeSpin()==FALSE) play=FALSE;
  667.                     else do { input = GetInput(); ChangePower(); }
  668.                     while (!(input==RETURN || input==ESC));
  669.                     
  670.                     if (input==ESC) play=FALSE;
  671.                     if (play) PlayShot();
  672.                     else
  673.                     {
  674.                         WriteMessage(MSG_SHOTCANCELLED,5,5,NEW);    
  675.                         cuespeed=MINSPEED; Delay(50);
  676.                         WriteMessage(player[turn].nametag,5,5,NEW);    
  677.                     }
  678.                 } break;
  679.                 
  680.             case LCSR: MoveCue(CLOCKWISE,SMALL); break;
  681.             case RCSR: MoveCue(ANTICLOCKWISE,SMALL); break;
  682.             case UCSR: MoveCue(CLOCKWISE,LARGE); break;
  683.             case DCSR: MoveCue(ANTICLOCKWISE,LARGE); break;
  684.             
  685.             case SPACE: do ChangePower(); while (cuespeed < (MAXSPEED/2));
  686.                 PlayShot(); break;
  687.             
  688.             case F1: DrawCue(OFF);
  689.                  if ((dotspacing+=2) > 12) dotspacing=4;
  690.                 DrawCue(ON); break;
  691.             
  692.             case F2: player[2].cuepulls = 1-player[2].cuepulls;
  693.                 player[0].cuepulls = player[2].cuepulls;
  694.                 player[3].cuepulls = 1-player[3].cuepulls;
  695.                 player[1].cuepulls = player[3].cuepulls;
  696.                 cuespeed=MAXSPEED; DrawCue(OFF);
  697.                 DrawCue(HIT); DrawCue(ON); cuespeed=MINSPEED; break;
  698.                 
  699.             case F3: DrawCue(OFF); cueline=(1-cueline); DrawCue(ON); break;
  700.             case F4: /* cheer toggle */
  701.                 if (cheer = 1-cheer) PlaySound(&audioinfo[CHEER],64);
  702.                 break;            
  703.             
  704.             case F5: /* smash balls */
  705.                 if (gametype==PRACTICE || dragcheat)
  706.                 {
  707.                     for (i=0; i<balls; i++)
  708.                     {
  709.                         ball[i].angle = Rand(360);
  710.                         ball[i].speed = MAXSPEED;
  711.                     }
  712.                     cuespeed = MAXSPEED; PlayShot();
  713.                 } break;
  714.  
  715.             case F6: if (gametype==PRACTICE || dragcheat)
  716.                 {
  717.                     DrawCue(OFF); SetUpTable();
  718.                     WriteMessage(player[turn].nametag,5,5,NEW);
  719.                 } break;
  720.                     
  721.             case 37: /* "hogan" win game cheat!!! */ key = 10; break;
  722.             case 24: if (key==10) key = 20; break;
  723.             case 36: if (key==20) key = 30; break;
  724.             case 32: if (key==30) key = 40; break;
  725.             case 54: if (key==40) { endofgame=TRUE; winner=HUMANPLYR; }
  726.                     break;
  727.             
  728.             case 25: /* "pixie" dragball cheat!!! */ key = 1; break;
  729.             case 23: if (key==1) key = 2; if (key==3) key = 4; break;
  730.             case 50: if (key==2) key = 3; break;
  731.             case 18: if (key==4) 
  732.                     {
  733.                         if (dragcheat=1-dragcheat) 
  734.                             SetPointer(w,pointeron,11,11,0,0);
  735.                         else SetPointer(w,pointeroff,1,1,0,0);
  736.                     } break;
  737.             
  738.             case HELP: if (gametype==PRACTICE || dragcheat)
  739.                      PlayComputerShot(); break;
  740.         }
  741.         if (quitgame)
  742.         {
  743.             if (gametype==DEMO)
  744.             {
  745.                 if (defaultdemo) for(i=0; i<8; i++) arg[i] = bufarg[i];
  746.                 defaultdemo=FALSE;
  747.                 WriteMessage(MSG_QUITTING,5,5,NEW); Delay(50);
  748.             }
  749.             else
  750.             {
  751.                 WriteMessage(MSG_QUITGAME,5,5,NEW);
  752.                 do input = GetInput();
  753.                     while (input!=21 && input!=54);
  754.                 if (input==54)
  755.                 {
  756.                     WriteMessage(player[turn].nametag,5,5,NEW);
  757.                     quitgame=FALSE;
  758.                 }
  759.                 else { WriteMessage(MSG_QUITTING,5,5,NEW); Delay(50); }
  760.             }
  761.         }
  762.         if (endofgame && gametype!=PRACTICE)
  763.         {
  764.             
  765.             player[winner].wins++;
  766.             if (gametype==PLYR1)
  767.             {
  768.                 if (winner==HUMANPLYR)
  769.                 {
  770.                     WriteMessage(MSG_WELLDONE,5,5,NEW);
  771.                     if (cheer) PlaySound(&audioinfo[LONGCHEER],64);
  772.                 }
  773.                 else WriteMessage(MSG_BADLUCK,5,5,NEW);
  774.                 Delay(75);
  775.             }
  776.             else if (cheer) PlaySound(&audioinfo[LONGCHEER],64);
  777.             WriteMessage(player[winner].nametag,5,5,NEW);
  778.             WriteMessage(MSG_WINS,0,5,FOLLOW);
  779.             Delay(100); ScrubMessage();
  780.             if (defaultdemo) for(i=0; i<8; i++) arg[i] = bufarg[i];
  781.             defaultdemo=FALSE;
  782.         }
  783.         if (gametype==PRACTICE || dragcheat) CheckBallDrag();
  784.     
  785.     } while(!quitgame && !endofgame);
  786.     DrawCue(OFF); SetPointer(w,pointeroff,1,1,0,0);
  787. }
  788. /**********************/
  789. void DrawCue(status)
  790. short status;
  791. {
  792.     short i,j,x1,y1,x2,y2,dx,dy,dirnlen=0,cuelen=MAXCUELENGTH,
  793.         viewline=cueline;
  794.     
  795.     if (gametype==DEMO || (gametype==PLYR1 && turn==COMPLYR)) viewline=0;
  796.     
  797.     rp->Mask = 31;
  798.     if (status == ON)
  799.     {
  800.         x1 = X1CORNER + (ball[CUE].x + CUETIP * quicksin[cueangle]
  801.             * quicksin[90+spinx/12]/BASE
  802.             - spinx/100 * quickcos[cueangle]) / BASE;
  803.             
  804.         y1 = (Y2CORNER-1) - (ball[CUE].y + CUETIP*quickcos[cueangle]
  805.             * quicksin[90+spinx/12]/BASE
  806.             + spinx/100 * quicksin[cueangle]) / BASE;
  807.         do
  808.         {
  809.             x2 = x1 +    cuelen * quicksin[cueangle]/BASE;
  810.             y2 = y1 - cuelen * quickcos[cueangle]/BASE;
  811.             cuelen--;
  812.     
  813.         } while (x2 < 1 || x2 > 318 || y2 < 33 || y2 > 254);
  814.     
  815.         blitdat.x = (x1 < x2)? x1-1:x2-1;
  816.         blitdat.y = (y1 < y2)? y1-1:y2-1;
  817.         blitdat.dx = abs(x1-x2)+3;
  818.         blitdat.dy = abs(y1-y2)+3;
  819.                 
  820.         BltBitMap(bm,blitdat.x,blitdat.y,&bufbm,
  821.             0,0,blitdat.dx,blitdat.dy,0xc0,31,buffer);
  822.     
  823.         SetAPen(rp,_cuecol);
  824.         for (dx=-1; dx<2; dx++) for (dy=-1; dy<2; dy++)
  825.         { Move(rp,x1,y1); Draw(rp,x2+dx,y2+dy); }
  826.     
  827.         SetAPen(rp,_ltcuecol); Move(rp,x1,y1); Draw(rp,x2,y2);
  828.         
  829.         SetAPen(rp,_black); WritePixel(rp,x1,y1);
  830.  
  831.         x1 = X1CORNER + ball[CUE].x/BASE - CUETIP*quicksin[cueangle]/BASE;
  832.         y1 = (Y2CORNER-1) - ball[CUE].y/BASE + CUETIP*quickcos[cueangle]/BASE;
  833.  
  834.         if (viewline)
  835.         {
  836.             SetAPen(rp,_white);
  837.     
  838.             for (i=0; i<32; i++,dirnlen+=dotspacing)
  839.             {
  840.                 x2 = x1 -    dirnlen * quicksin[cueangle]/BASE;
  841.                 y2 = y1 +    dirnlen * quickcos[cueangle]/BASE;
  842.  
  843.                 for (j=0; j<2; j++)
  844.                 {
  845.                     if (y2 < (Y1CORNER+7)) y2 += ((Y1CORNER+7)-y2)<<1;
  846.                     if (y2 > (Y2CORNER-7)) y2 -= (y2-(Y2CORNER-7))<<1;
  847.                     if (y2 < (Y1CORNER+7)) y2 += ((Y1CORNER+7)-y2)<<1;
  848.                     if (x2 < (X1CORNER+7)) x2 += ((X1CORNER+7)-x2)<<1;
  849.                     if (x2 > (X2CORNER-7)) x2 -= (x2-(X2CORNER-7))<<1;
  850.                     if (x2 < (X1CORNER+7)) x2 += ((X1CORNER+7)-x2)<<1;
  851.                 }
  852.                 pixelsave[i].col = ReadPixel(rp,x2,y2);
  853.                 pixelsave[i].x = x2;
  854.                 pixelsave[i].y = y2;
  855.             }
  856.             for (i=0; i<32; i++)
  857.                 WritePixel(rp,pixelsave[i].x,pixelsave[i].y);
  858.         }
  859.     }
  860.     else if (status==OFF)
  861.     {
  862.         if (viewline)
  863.         {
  864.             WaitBOVP(vp);
  865.             for (i=31; i>=0; i--)
  866.             {
  867.                 SetAPen(rp,pixelsave[i].col);
  868.                 WritePixel(rp,pixelsave[i].x,pixelsave[i].y);
  869.             }
  870.         }
  871.         WaitBeam(blitdat.y+blitdat.dy);
  872.         BltBitMap(&bufbm,0,0,bm,
  873.             blitdat.x,blitdat.y,blitdat.dx,blitdat.dy,0xc0,31,buffer);
  874.     }
  875.     else if (status==HIT)
  876.     {
  877.         char firstrun = 0,stage;
  878.         short offset;
  879.         
  880.         for (stage=0; stage<player[turn].cuepulls+1; stage++)
  881.         for (i=0; i<=180; i+=15)
  882.         {
  883.             if (stage==player[turn].cuepulls)
  884.                 offset = quicksin[i]*60*cuespeed/MAXSPEED/BASE;
  885.  
  886.             else offset = (BASE-quickcos[i+i])
  887.                 *15*cuespeed/MAXSPEED/BASE;
  888.             
  889.             cuelen = MAXCUELENGTH;
  890.  
  891.             x1 = X1CORNER + (ball[CUE].x + CUETIP * quicksin[cueangle]
  892.                 * quicksin[90+spinx/12]/BASE
  893.                 - spinx/100 * quickcos[cueangle]
  894.                 + offset*quicksin[cueangle]) / BASE;
  895.             
  896.             y1 = (Y2CORNER-1) - (ball[CUE].y + CUETIP*quickcos[cueangle]
  897.                 * quicksin[90+spinx/12]/BASE
  898.                 + spinx/100 * quicksin[cueangle]
  899.                 + offset*quickcos[cueangle]) / BASE;
  900.  
  901.             if (x1 < 1 || x1 > 318 || y1 < 33 || y1 > 254) continue;
  902.  
  903.             do
  904.             {
  905.                 x2 = x1 +    cuelen * quicksin[cueangle]/BASE;
  906.                 y2 = y1 - cuelen * quickcos[cueangle]/BASE;
  907.                 cuelen--;
  908.     
  909.             } while (x2 < 1 || x2 > 318 || y2 < 33 || y2 > 254);
  910.     
  911.             if (!firstrun)
  912.             {
  913.                 Delay(1); WaitBeam(blitdat.y+blitdat.dy);
  914.                 BltBitMap(&bufbm,0,0,bm,blitdat.x,blitdat.y,
  915.                     blitdat.dx,blitdat.dy,0xc0,31,buffer);
  916.             }
  917.  
  918.             blitdat.x = (x1 < x2)? x1-1:x2-1;
  919.             blitdat.y = (y1 < y2)? y1-1:y2-1;
  920.             blitdat.dx = abs(x1-x2)+3;
  921.             blitdat.dy = abs(y1-y2)+3;
  922.             
  923.             BltBitMap(bm,blitdat.x,blitdat.y,&bufbm,
  924.                 0,0,blitdat.dx,blitdat.dy,0xc0,31,buffer);
  925.         
  926.             SetAPen(rp,_cuecol);
  927.             for (dx=-1; dx<2; dx++) for (dy=-1; dy<2; dy++)
  928.             { Move(rp,x1,y1); Draw(rp,x2+dx,y2+dy); }
  929.     
  930.             SetAPen(rp,_ltcuecol); Move(rp,x1,y1); Draw(rp,x2,y2);
  931.             SetAPen(rp,_black); WritePixel(rp,x1,y1);
  932.             firstrun = 0;
  933.         }
  934.         WaitBeam(blitdat.y+blitdat.dy);
  935.         BltBitMap(&bufbm,0,0,bm,blitdat.x,blitdat.y,
  936.             blitdat.dx,blitdat.dy,0xc0,31,buffer);
  937.     }
  938. }
  939. /***********************/
  940. void MakeCollision(i,j)
  941. short i,j;
  942. {
  943.     short dx,dy,volume,theta,dxi,dxj,dyi,dyj,
  944.         reldx,reldy,relspeed,relangle,
  945.         passx,passy,transfer,intersect,jump=FALSE;
  946.  
  947.     dx = ball[j].x - ball[i].x;
  948.     dy = ball[j].y - ball[i].y;
  949.     intersect = BALLDIAMETER - QuickRoot(dx*dx + dy*dy);
  950.     
  951.     if (i==CUE && ball[CUE].speed > (MAXSPEED*3/4) &&
  952.         spiny < -600 && !(Rand(2))) { jump=TRUE; CueJumpAnim(); }
  953.     
  954.     /* Find pure offsets */
  955.     dxi = ball[i].speed * quicksin[ball[i].angle] / BASE;
  956.     dyi = ball[i].speed * quickcos[ball[i].angle] / BASE;
  957.     dxj = ball[j].speed * quicksin[ball[j].angle] / BASE;
  958.     dyj = ball[j].speed * quickcos[ball[j].angle] / BASE;
  959.     
  960.     /* Ball i relative offsets - makes ball j static */
  961.     reldx = dxi - dxj;
  962.     reldy = dyi - dyj;
  963.     
  964.     relspeed = QuickRoot(reldx*reldx + reldy*reldy);
  965.  
  966.     /* Reposition balls so that they collide at surface */
  967.     if (relspeed > BASE && packstate==SPREAD)
  968.     {
  969.         dx = (ball[j].x - dxj * intersect / relspeed) -
  970.             (ball[i].x - dxi * intersect / relspeed);
  971.         
  972.         dy = (ball[j].y - dyj * intersect / relspeed) -
  973.             (ball[i].y - dyi * intersect / relspeed);
  974.     }
  975.     theta = FindAngle(dx,dy,BALLDIAMETER);
  976.     /* Common angle between balls */
  977.     
  978.     relangle = FindAngle(reldx,reldy,relspeed);
  979.     /* Find angle of relative velocity */
  980.     
  981.     /* Power transfer from one ball to another */
  982.     transfer = abs(quickcos[abs(theta - relangle)])*relspeed*3/BASE/4;
  983.         
  984.     passx = transfer * quicksin[theta] / BASE;
  985.     passy = transfer * quickcos[theta] / BASE;
  986.  
  987.     if (i==CUE && spiny)
  988.     {
  989.         dxi += dxi * spiny / 800 * 
  990.             abs(quickcos[abs(theta - relangle)]) / BASE;
  991.         dyi += dyi * spiny / 800 * 
  992.             abs(quickcos[abs(theta - relangle)]) / BASE;
  993.         spiny=0; swerve=0;
  994.     }    
  995.  
  996.     dxj += passx; dyj += passy;
  997.     dxi -= passx; dyi -= passy;
  998.             
  999.     ball[i].speed = QuickRoot(dxi*dxi + dyi*dyi);
  1000.     if (ball[i].speed > MAXSPEED) ball[i].speed = MAXSPEED;
  1001.     else if (ball[i].speed < 6) ball[i].speed = 6;
  1002.     if (ball[i].speed) ball[i].angle = FindAngle(dxi,dyi,ball[i].speed);
  1003.     
  1004.     ball[j].speed = QuickRoot(dxj*dxj + dyj*dyj);
  1005.     if (ball[j].speed > MAXSPEED) ball[j].speed = MAXSPEED;
  1006.     else if (ball[j].speed < 6) ball[j].speed = 6;
  1007.     if (ball[j].speed) ball[j].angle = FindAngle(dxj,dyj,ball[j].speed);
  1008.     
  1009.     if (i==CUE && spinx)
  1010.     {
  1011.         ball[CUE].angle-=spinx/25;
  1012.         CheckAngle(&ball[CUE].angle);
  1013.         spinx=0; swerve=0;
  1014.     }
  1015.     ball[i].lasthit = j; ball[j].lasthit = i;
  1016.     
  1017.     if (cheatangle!=-1 && j==cheatball)
  1018.     {
  1019.         ball[j].angle = cheatangle;
  1020.         if (ball[j].speed < ball[CUE].speed>>2)
  1021.             ball[j].speed = ball[CUE].speed>>2; 
  1022.     }
  1023.     cheatangle=-1;
  1024.     
  1025.     if ((packstate!=BROKEN || !newbreak) && !jump)
  1026.     {
  1027.         /* Prevent multiple collisions on break */
  1028.         if ((volume = 16 + (transfer<<6)/MAXSPEED) > 64) volume = 64;
  1029.         PlaySound(&audioinfo[COLLIDE],volume);
  1030.         if (packstate==RACKED) packstate=BROKEN;
  1031.     }    
  1032.     /* Check for a foul shot here */
  1033.     if (i==CUE && !firsthit) firsthit=j;
  1034. }
  1035.  
  1036. /*********************/
  1037. #define ENCRYPTCODE 0xd6
  1038.  
  1039. long MyRead(fh,ptr,len)
  1040. struct FileHandle *fh;
  1041. long *ptr;
  1042. long len;
  1043. {
  1044.     long retnlen;
  1045.     
  1046.     retnlen = Read((BPTR)fh,ptr,len);
  1047.     len = retnlen;
  1048.     {
  1049.         register char *ptr2 = (char *)ptr;
  1050.         
  1051.         while (len > 3)
  1052.         {
  1053.             *ptr2++ ^= ENCRYPTCODE; *ptr2++ ^= ENCRYPTCODE;
  1054.             *ptr2++ ^= ENCRYPTCODE; *ptr2++ ^= ENCRYPTCODE;
  1055.             len -= 4;
  1056.         }
  1057.         while (len) { *ptr2++ ^= ENCRYPTCODE; len--; }
  1058.     }
  1059.     return retnlen;
  1060. }
  1061.